package com.shoppingmall.service.impl;

import com.alipay.api.AlipayResponse;
import com.alipay.api.response.AlipayTradePrecreateResponse;
import com.alipay.demo.trade.config.Configs;
import com.alipay.demo.trade.model.ExtendParams;
import com.alipay.demo.trade.model.GoodsDetail;
import com.alipay.demo.trade.model.builder.AlipayTradePrecreateRequestBuilder;
import com.alipay.demo.trade.model.result.AlipayF2FPrecreateResult;
import com.alipay.demo.trade.service.AlipayTradeService;
import com.alipay.demo.trade.service.impl.AlipayTradeServiceImpl;
import com.alipay.demo.trade.utils.ZxingUtils;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.shoppingmall.common.Constant;
import com.shoppingmall.common.ServletResponse;
import com.shoppingmall.dao.*;
import com.shoppingmall.pojo.*;
import com.shoppingmall.service.OrderService;
import com.shoppingmall.utils.BigDecimalUtils;
import com.shoppingmall.utils.DateTransform;
import com.shoppingmall.vo.OrderVo;
import com.sun.org.apache.bcel.internal.generic.RETURN;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.aspectj.weaver.ast.Or;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;

/**
 * Created by
 *
 * @author touni
 * @date 2019/3/25
 * @time 12:43
 */
@Service
public class OrderServiceImpl implements OrderService {

    private static final Logger log = LoggerFactory.getLogger(OrderServiceImpl.class);


    @Value("${ALIPAY_CALL_BACK_URL}")
    private String ALIPAY_CALL_BACK_URL;


    // 支付宝当面付2.0服务
    private static AlipayTradeService tradeService;

    @Autowired
    private ShippingMapper shippingMapper;


    @Autowired
    private OrderMapper orderMapper;


    @Autowired
    private OrderItemMapper orderItemMapper;

    @Autowired
    private PayInfoMapper payInfoMapper;


    @Autowired
    private CartMapper cartMapper;

    @Autowired
    private ProductMapper productMapper;


    static {
        /** 一定要在创建AlipayTradeService之前调用Configs.init()设置默认参数
         *  Configs会读取classpath下的zfbinfo.properties文件配置信息，如果找不到该文件则确认该文件是否在classpath目录
         */
        Configs.init("zfbinfo.properties");

        /** 使用Configs提供的默认参数
         *  AlipayTradeService可以使用单例或者为静态成员对象，不需要反复new
         */
        tradeService = new AlipayTradeServiceImpl.ClientBuilder().build();
    }




        /**
         * 支付宝支付
         * @param userId
         * @param orderId
         * @return
         */
    @Override
    public ServletResponse alipayOrder(Integer userId, Long orderId) {
        //通过orderId和userId来查询是否有这个订单
        Order orderFromQuery = orderMapper.selectOrderByuserIdAndOrderId(userId,orderId);
        if (null == orderFromQuery){
            return  ServletResponse.createByErrorMessage("该订单不存在，请重新下单");
        }
        // (必填) 商户网站订单系统中唯一订单号，64个字符以内，只能包含字母、数字、下划线，
        // 需保证商户系统端不能重复，建议通过数据库sequence生成，
        String outTradeNo = orderId.toString();

        // (必填) 订单标题，粗略描述用户的支付目的。如“xxx品牌xxx门店当面付扫码消费”
        String subject = new StringBuilder().append("订单").append(orderId).append("支付").toString();

        // (必填) 订单总金额，单位为元，不能超过1亿元
        // 如果同时传入了【打折金额】,【不可打折金额】,【订单总金额】三者,则必须满足如下条件:【订单总金额】=【打折金额】+【不可打折金额】
        String totalAmount = orderFromQuery.getPayment().toString();

        // (可选) 订单不可打折金额，可以配合商家平台配置折扣活动，如果酒水不参与打折，则将对应金额填写至此字段
        // 如果该值未传入,但传入了【订单总金额】,【打折金额】,则该值默认为【订单总金额】-【打折金额】
        String undiscountableAmount = "0";

        // 卖家支付宝账号ID，用于支持一个签约账号下支持打款到不同的收款账号，(打款到sellerId对应的支付宝账号)
        // 如果该字段为空，则默认为与支付宝签约的商户的PID，也就是appid对应的PID
        String sellerId = "";

        // 订单描述，可以对交易或商品进行一个详细地描述，比如填写"购买商品2件共15.00元"
        String body = "详情请登录网址查看";

        // 商户操作员编号，添加此参数可以为商户操作员做销售统计
        String operatorId = "test_operator_id";

        // (必填) 商户门店编号，该配置目前暂时不配置  通过门店号和商家后台可以配置精准到门店的折扣信息，详询支付宝技术支持
        String storeId = "test_store_id";

        // 业务扩展参数，目前可添加由支付宝分配的系统商编号(通过setSysServiceProviderId方法)，详情请咨询支付宝技术支持
        ExtendParams extendParams = new ExtendParams();
        extendParams.setSysServiceProviderId("2088100200300400500");

        // 支付超时，定义为120分钟
        String timeoutExpress = "120m";

        // 商品明细列表，需填写购买商品详细信息  需要先查询orderitem表
        List<OrderItem> orderItemList = orderItemMapper.selectOrderItemByOrderId(orderId);
        List<GoodsDetail> goodsDetailList = new ArrayList<GoodsDetail>();
        for (OrderItem orderItem : orderItemList){

            // 创建一个商品信息，参数含义分别为商品id（使用国标）、名称、单价（单位为分）、数量，如果需要添加商品类别，详见GoodsDetail
            GoodsDetail goods = GoodsDetail.newInstance(orderItem.getProductId().toString(), orderItem.getProductName(), orderItem.getCurrentUnitPrice().longValue(), orderItem.getQuantity());
            // 创建好一个商品后添加至商品明细列表
            goodsDetailList.add(goods);

        }

        // 创建扫码支付请求builder，设置请求参数
        AlipayTradePrecreateRequestBuilder builder = new AlipayTradePrecreateRequestBuilder()
                .setSubject(subject).setTotalAmount(totalAmount).setOutTradeNo(outTradeNo)
                .setUndiscountableAmount(undiscountableAmount).setSellerId(sellerId).setBody(body)
                .setOperatorId(operatorId).setStoreId(storeId).setExtendParams(extendParams)
                .setTimeoutExpress(timeoutExpress)
                .setNotifyUrl("http://5c7vi9.natappfree.cc/shoppingmall_war/order/alipay_call_back.do")//支付宝服务器主动通知商户服务器里指定的页面http路径,根据需要设置
                .setGoodsDetailList(goodsDetailList);

        AlipayF2FPrecreateResult result = tradeService.tradePrecreate(builder);
        switch (result.getTradeStatus()) {
            case SUCCESS:
                log.info("支付宝预下单成功: )");

                AlipayTradePrecreateResponse response = result.getResponse();
                dumpResponse(response);

                // 需要修改为运行机器上的路径
                String filePath = String.format("E:\\alipay-paycode\\qr-%s.png",
                        response.getOutTradeNo());
                log.info("filePath:" + filePath);
                ZxingUtils.getQRCodeImge(response.getQrCode(), 256, filePath);
                Map<String,String> payResultMap = Maps.newHashMap();
                payResultMap.put("OrderId",orderId.toString());
                payResultMap.put("payCodeUrl",filePath);

                return ServletResponse.createBySuccess(payResultMap);


            case FAILED:
                log.error("支付宝预下单失败!!!");
                return ServletResponse.createByErrorMessage("支付宝预下单失败");

            case UNKNOWN:
                log.error("系统异常，预下单状态未知!!!");
                return ServletResponse.createByErrorMessage("系统异常，预下单状态未知!!!");

            default:
                log.error("不支持的交易状态，交易返回异常!!!");
                return ServletResponse.createByErrorMessage("不支持的交易状态，交易返回异常!!!");
        }








    }


    /**
     * 验签通过  对数据库进行操作
     * @param params
     * @return
     */
    @Override
    public ServletResponse alipayCallBack(Map<String, String> params) {
        //商户需要验证该通知数据中的out_trade_no是否为商户系统中创建的订单号，并判断total_amount是否确实为该订单的实际金额（即商户订单创建时的金额），
        // 同时需要校验通知中的seller_id（或者seller_email) 是否为out_trade_no这笔单据的对应的操作方
        // （有的时候，一个商户可能有多个seller_id/seller_email），上述有任何一个验证不通过，则表明本次通知是异常通知，务必忽略。
        String seller_id = params.get("seller_id");
        if (!Configs.getPid().equals(seller_id)){
            return ServletResponse.createByErrorMessage("参数验证失败");
        }
        Long orderId= Long.valueOf(params.get("out_trade_no"));
        Double total_amount = Double.parseDouble(params.get("total_amount"));
        Order orderQueryByTradeNo = orderMapper.selectOrderByOrderId(orderId);
        if (null == orderQueryByTradeNo){
            return ServletResponse.createByErrorMessage("参数验证失败！！");
        }
        if (total_amount.longValue() != orderQueryByTradeNo.getPayment().doubleValue()){
            return ServletResponse.createByErrorMessage("参数验证失败！！");
        }
        //获取支付宝返回的trade_status    更新数据库订单的状态
        //判断是否有重复的通知
        if (orderQueryByTradeNo.getStatus() >= Constant.OrderStatusEnum.PAID.getCode()){
            return ServletResponse.createBySuccessMessage("支付宝重复通知");
        }
        //判断支付宝返回的交易状态
        String trade_status = params.get("trade_status");
        if (!Constant.AlipayCallback.TRADE_STATUS_TRADE_SUCCESS.equals(trade_status)){
            //没有付款成功，等待付款的状态
            return ServletResponse.createBySuccess();

        }
        //付款成功，修改数据库
        orderQueryByTradeNo.setPaymentTime(DateTransform.strToDate(params.get("gmt_payment")));
        orderQueryByTradeNo.setStatus(Constant.OrderStatusEnum.PAID.getCode());
        int flag = orderMapper.updateByPrimaryKeySelective(orderQueryByTradeNo);
        if (1 != flag){
            log.info("修改数据库状态失败");
        }
        log.info("付款成功，更新数据库状态成功！！");

        //封装payinfo
        PayInfo payInfo = new PayInfo();
        payInfo.setOrderNo(orderId);
        //设置支付平台，支付宝为1
        payInfo.setPayPlatform(1);
        //设置支付宝交易号
        payInfo.setPlatformNumber(params.get("trade_no"));
        payInfo.setUserId(orderQueryByTradeNo.getUserId());
        payInfo.setPlatformStatus(trade_status);
        flag = payInfoMapper.insert(payInfo);
        if (1 != flag){
            log.info("更新payinfo表失败");
        }


        return ServletResponse.createBySuccess();
    }


    /**
     *  根据用户id和订单id来查询这个订单的状态
     * @param userId
     * @param orderId
     * @return
     */
    @Override
    public ServletResponse queryOrderPayStatus(Integer userId, Long orderId) {
        Order orderByuserIdAndOrderId = orderMapper.selectOrderByuserIdAndOrderId(userId, orderId);
        if (null ==orderByuserIdAndOrderId){
            return ServletResponse.createByErrorMessage("未查询到这个订单！！！");
        }
        return ServletResponse.createBySuccess(orderByuserIdAndOrderId);
    }

    @Override
    public ServletResponse createOrder(Integer userId, Integer shippingId) {
        //根据用户id在数据库中查询出已选的商品
        List<Cart> cartList = cartMapper.selectByUserIdChecked(userId);
        //查询出来后，需要把购物车清空
        cartMapper.deleteCartByUserId(userId);
        if (CollectionUtils.isEmpty(cartList)){
            return ServletResponse.createByErrorMessage("用户未选中商品，无法下单");
        }
        //先 生成一个Long的orderId  注意可能会产生负数
        Long orderId = Long.valueOf(System.currentTimeMillis()+new Random().nextLong());

        //先插入order_item表中
        for (Cart cart : cartList){
            //组装orderitem
            OrderItem orderItem = new OrderItem();
            orderItem.setUserId(userId);
            orderItem.setOrderNo(orderId);
            orderItem.setProductId(cart.getProductId());
            Product product = productMapper.selectByPrimaryKey(cart.getProductId());
            orderItem.setProductName(product.getName());
            orderItem.setProductImage(product.getMainImage());
            orderItem.setCurrentUnitPrice(product.getPrice());
            orderItem.setQuantity(cart.getQuantity());
            orderItem.setTotalPrice(BigDecimalUtils.multiplyData(product.getPrice().toString(), cart.getQuantity().toString()));
            int flag = orderItemMapper.insert(orderItem);
            if (1 != flag){
                log.info(product.getId()+"插入orderitem失败");
            }

        }
        //组装order
        Order order = new Order();
        order.setOrderNo(orderId);
        order.setUserId(userId);
        order.setShippingId(shippingId);
        order.setPayment(getCartTotalPrice(cartList));
        //邮费暂时设置为0
        order.setPostage(0);
        //设置订单状态
        order.setStatus(Constant.OrderStatusEnum.NO_PAY.getCode());
        int flag = orderMapper.insert(order);
        if (1 !=flag){
            log.info(orderId+"更新order表失败");
        }
        OrderVo orderVo = getOrderVo(userId, orderId);
        return ServletResponse.createBySuccess(orderVo);
    }

    /**
     * 根据用户ID 查询所有的下单的商品
     * @param userId
     * @return
     */
    @Override
    public ServletResponse getAllOrderProduct(Integer userId) {
        BigDecimal totalPrice = new BigDecimal(0);
        List<OrderItem> orderItemList = orderItemMapper.selectOrderItemByUserId(userId);
        if (null == orderItemList){
            return ServletResponse.createByErrorMessage("该用户暂无订单");
        }
        for (OrderItem orderItem : orderItemList){
            BigDecimal productPrice = BigDecimalUtils.multiplyData(orderItem.getCurrentUnitPrice().toString(), orderItem.getQuantity().toString());
            totalPrice = totalPrice.add(productPrice);
        }
        Map<String, Object> resultMap = Maps.newHashMap();
        resultMap.put("orderItemVoList",orderItemList);
        resultMap.put("productTotalPrice",totalPrice);
        return ServletResponse.createBySuccess(resultMap);
    }

    /**
     * 根据用户ID查询所有的用户的订单
     * @param userId
     * @return
     */
    @Override
    public ServletResponse listAllOrder(Integer userId,Integer pageSize,Integer pageNum) {
        //设置查询条件
        PageHelper.startPage(pageNum,pageSize);
        //执行查询逻辑
        List<Order> orderList = orderMapper.selectOrderByUserId(userId);
        if (CollectionUtils.isEmpty(orderList)){
            return ServletResponse.createByErrorMessage("用户尚未有订单呢");
        }
        List<OrderVo> list = Lists.newArrayList();
        for (Order order : orderList){
            OrderVo orderVo = getOrderVo(userId, order.getOrderNo());
            list.add(orderVo);
        }
        PageInfo pageInfo = new PageInfo(list);

        return ServletResponse.createBySuccess(pageInfo);
    }

    @Override
    public ServletResponse queryOrderDetail(Integer userId, Long orderNo) {
        OrderVo orderVo = getOrderVo(userId, orderNo);
        if (null == orderVo){
            return ServletResponse.createByErrorMessage("用户没有此订单");
        }

        return ServletResponse.createBySuccess(orderVo);
    }

    @Override
    public ServletResponse cancelOrder(Integer userId, Long orderNo) {
        Order order = orderMapper.selectOrderByuserIdAndOrderId(userId, orderNo);
        if (null == order){
            return ServletResponse.createByErrorMessage("此订单不存在");
        }
        if (null==order.getStatus() ||order.getStatus().intValue() >= 20){
            return ServletResponse.createByErrorMessage("订单支付成功，无法取消！！");
        }
        //将订单状态置位0 表示的是取消的意思
        order.setStatus(0);
        int flag = orderMapper.updateByPrimaryKeySelective(order);
        if (1!= flag){
            return ServletResponse.createByErrorMessage("订单状态修改失败，请稍后重试！！");

        }
        return ServletResponse.createBySuccess("订单取消成功",0);
    }

    @Override
    public ServletResponse managerListAllUserOrder(Integer pageSize,Integer pageNum) {
        PageHelper.startPage(pageNum,pageSize);
        List<OrderVo> resultList = Lists.newArrayList();
        List<Order> allOrderList = orderMapper.selectAllOrder();
        for (Order order : allOrderList){
            OrderVo orderVo = getOrderVo(null, order.getOrderNo());
            resultList.add(orderVo);
        }
        PageInfo pageInfo = new PageInfo(resultList);


        return ServletResponse.createBySuccess(pageInfo);
    }

    @Override
    public ServletResponse searchOrderByOrderNo(Long orderNo) {
        OrderVo orderVo = getOrderVo(null, orderNo);
        if (null == orderVo){
            return ServletResponse.createByErrorMessage("查无此订单");
        }
        return ServletResponse.createBySuccess(orderVo);
    }

    /**
     * 需要封装shipping表
     * @param orderNo
     * @return
     */
    @Override
    public ServletResponse queryOrderDetailByOrderNu(Long orderNo) {
        OrderVo orderVo = getOrderVo(null, orderNo);
        if (null == orderVo){
            return ServletResponse.createByErrorMessage("该订单不存在，请重新输入订单号");
        }
        Integer shippingId = orderVo.getShippingId();
        Shipping shipping = shippingMapper.selectByPrimaryKey(shippingId);
        if (null == shipping){
            return ServletResponse.createBySuccess("查询不到购物的地址列表",orderVo);
        }
        orderVo.setShippingVo(shipping);
        return ServletResponse.createBySuccess(orderVo);


    }

    @Override
    public ServletResponse sendGoods(Long orderNo) {
        Order order = orderMapper.selectOrderByOrderId(orderNo);
        if (null == order){
            return ServletResponse.createByErrorMessage("订单不存在，发货失败");
        }
        order.setStatus(Constant.OrderStatusEnum.SHIPPED.getCode());
        order.setSendTime(new Date());
        int flag = orderMapper.updateByPrimaryKeySelective(order);
        if (1 != flag){
            return ServletResponse.createByErrorMessage("更新状态失败");
        }


        return ServletResponse.createBySuccess("发货成功");
    }

    /**
     * 根据购物车内的商品查询总价
     * @param cartList
     * @return
     */
    private BigDecimal getCartTotalPrice(List<Cart> cartList){
        BigDecimal totalPrice = new BigDecimal(0);
        for(Cart cart : cartList){
            Integer productId = cart.getProductId();
            Product product = productMapper.selectByPrimaryKey(productId);
            product.getPrice();
            cart.getQuantity();
            BigDecimal productTotalPrice = BigDecimalUtils.multiplyData(product.getPrice().toString(), cart.getQuantity().toString());
            totalPrice = totalPrice.add(productTotalPrice);

        }
        return totalPrice;
    }

    /**
     * 内部通用方法，用来封装一个ordervo对象
     * @return
     */
    private OrderVo getOrderVo(Integer userId,Long orderId){
        //根据userId和orderId来组装ordervo  userId可以为空
        OrderVo orderVo = new OrderVo();
        //查询orderitem封装 orderItemList
        List<OrderItem> orderItemList = null;
        if (null != userId) {
            orderItemList = orderItemMapper.selectOrderItemByOrderIdAndUserId(userId, orderId);
        }else {
            orderItemList = orderItemMapper.selectOrderItemByOrderId(orderId);
        }
        orderVo.setOrderItemVoList(orderItemList);
        Order order = null;
        if (null != userId) {
            order = orderMapper.selectOrderByuserIdAndOrderId(userId, orderId);
        }else {
            order = orderMapper.selectOrderByOrderId(orderId);
        }
        orderVo.setId(order.getId());
        orderVo.setOrderNo(orderId);
        orderVo.setUserId(order.getUserId());
        orderVo.setPayment(order.getPayment());
        orderVo.setPaymentType(order.getPaymentType());
        orderVo.setPostage(order.getPostage());
        orderVo.setStatus(order.getStatus());
        orderVo.setPaymentTime(order.getPaymentTime());
        orderVo.setSendTime(order.getSendTime());
        orderVo.setEndTime(order.getEndTime());
        orderVo.setCloseTime(order.getCloseTime());
        orderVo.setCreateTime(order.getCreateTime());
        orderVo.setShippingId(order.getShippingId());
        return orderVo;
    }






    // 简单打印应答
    private void dumpResponse(AlipayResponse response) {
        if (response != null) {
            log.info(String.format("code:%s, msg:%s", response.getCode(), response.getMsg()));
            if (StringUtils.isNotEmpty(response.getSubCode())) {
                log.info(String.format("subCode:%s, subMsg:%s", response.getSubCode(),
                        response.getSubMsg()));
            }
            log.info("body:" + response.getBody());
        }
    }



}
